#include "main.h"
#include "module_key.h"

#define BEGIN_PERIOD_CTRL_MS(_ms_) { \
    static u32 start_tick = 0; \
    if (g_system_tick - start_tick >= _ms_) \
    { \
        start_tick = g_system_tick;
        
#define END_PERIOD_CTRL_MS()  } \
    }

extern u32 SystemCoreClock;
volatile u32 g_system_tick;

void UART1_Init(u32 bound)
{
    UART_InitTypeDef UART_InitStructure;

    UART_StructInit(&UART_InitStructure);
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_UART1, ENABLE);

    //set as 8-N-1 Customer can change below parameters
    UART_InitStructure.BaudRate       = bound;
    UART_InitStructure.WordLength     = UART_WordLength_8b;
    UART_InitStructure.StopBits       = UART_StopBits_1;
    UART_InitStructure.Parity         = UART_Parity_No;
    UART_InitStructure.Mode           = UART_Mode_Tx;
    UART_InitStructure.HWFlowControl  = UART_HWFlowControl_None;

    UART_Init(UART1, &UART_InitStructure);
    UART_Cmd(UART1, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit(&GPIO_InitStructure);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);
    //UART1_TX   GPIOA.12
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void dbg_print_string(char *str)
{
    while (*str != '\0')
    {
        UART_SendData(UART1, *str);
        str++;
        while(!UART_GetFlagStatus(UART1, UART_FLAG_TXEPT));
    }
}

void key_test(void)
{
    if (api_key.is_valid()) // 查询按键状态
    {
        if (api_key.is_click(KEY2)) dbg_print_string("KEY2 click!\n");
        if (api_key.is_double_click(KEY2)) dbg_print_string("KEY2 double click!\n");
        
        // dbg_print_string("\n");
        uint8_t key0_is_valid, key1_is_valid;
        static uint8_t s_mode = 0;
        if (s_mode == 0)
        {
            key0_is_valid = api_key.is_click(KEY0);
            key1_is_valid = api_key.is_click(KEY1);
            if (key0_is_valid && key1_is_valid) dbg_print_string("FUN7 (KEY0 KEY1 click)!\n");
            else if (key0_is_valid) dbg_print_string("FUN1 (KEY0 click)!\n");
            else if (key1_is_valid) dbg_print_string("FUN2 (KEY1 click)!\n");

            key0_is_valid = api_key.is_double_click(KEY0);
            key1_is_valid = api_key.is_double_click(KEY1);
            if (key0_is_valid && key1_is_valid) dbg_print_string("FUN8 (KEY0 KEY1 double click)!\n");
            else if (key0_is_valid) dbg_print_string("FUN3 (KEY0 double click)!\n");
            else if (key1_is_valid) dbg_print_string("FUN4 (KEY1 double click)!\n");

            key0_is_valid = api_key.is_long_press(KEY0);
            key1_is_valid = api_key.is_long_press(KEY1);
            if (key0_is_valid && key1_is_valid) dbg_print_string("FUN9 (KEY0 KEY1 long press)!\n");
            else if (key0_is_valid)
            {
                s_mode = 1;
                dbg_print_string("FUN5 (KEY0 long press)!\n");
            }
            else if (key1_is_valid)
            {
                s_mode = 2;
                dbg_print_string("FUN6 (KEY1 long press)!\n");
            }
            
            if (api_key.is_long_release(KEY0)) dbg_print_string("     (KEY0 long release)!\n");
            if (api_key.is_long_release(KEY1)) dbg_print_string("     (KEY1 long release)!\n");
        }
        else if (s_mode == 1)
        {
            if (api_key.is_click(KEY1)) dbg_print_string("FUN10 (KEY1 click)!\n");
            if (api_key.is_double_click(KEY1)) dbg_print_string("FUN11 (KEY1 double click)!\n");
            if (api_key.is_long_press(KEY1)) dbg_print_string("FUN12 (KEY1 long press)!\n");
            if (api_key.is_long_release(KEY0))
            {
                dbg_print_string("     (KEY0 long release)!\n");
                s_mode = 0;
            }
        }
        else if (s_mode == 2)
        {
            if (api_key.is_click(KEY0)) dbg_print_string("FUN13 (KEY0 click)!\n");
            if (api_key.is_double_click(KEY0)) dbg_print_string("FUN14 (KEY0 double click)!\n");
            if (api_key.is_long_press(KEY0)) dbg_print_string("FUN15 (KEY0 long press)!\n");
            if (api_key.is_long_release(KEY1))
            {
                dbg_print_string("     (KEY1 long release)!\n");
                s_mode = 0;
            } 
        }
        else
        {
            s_mode = 0;
        }
    }
}

void delay_ms(uint16_t ms)
{
    uint32_t tick_start = g_system_tick;
    while ((uint32_t)(g_system_tick - tick_start) < ms) // SYSTEM_MS_TO_TICK(ms))
    {
        //... // 喂狗
        //... // 解决未使用RTOS，阻塞延时期间，需周期性处理部分的问题
        fsl_single_key_loop(g_system_tick);
    }
}

static void key_indicate_cb(void)
{
    // key_test();
}

int main(void)
{
    // System Tick 周期1ms
    if (SysTick_Config(SystemCoreClock / 1000)) {
        while (1);
    }
    NVIC_SetPriority(SysTick_IRQn, 0x0);

    // 初始化调试串口
    UART1_Init(115200);

    // 初始化按键模块
    api_key.init(); 
    // 注册按键回调函数(可选)
    // api_key.register_indicate_callback(key_indicate_cb);// 裸机一般不需要，RTOS可用也可不用

    dbg_print_string("\n==> TEST START ==>\n");
    
    for(;;)
    {
        // 10ms循环控制
        BEGIN_PERIOD_CTRL_MS(10);

        fsl_single_key_loop(10);            // 形式1：入参为循环周期（ms）
        //fsl_single_key_loop(g_system_tick); // 形式2：入参为全局嘀嗒计数变量（ms）

        END_PERIOD_CTRL_MS();
        
        //
        // delay_ms(10000);
        
        
        // 应用层按键测试
        key_test();
    }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  SysTick_Handler is call from interrupt map
/// @note   Call delay count function.
/// @param  None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void SysTick_Handler(void)
{
    g_system_tick++;
}
